package com.example.sprintboot.controller;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.example.sprintboot.common.Result;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import com.example.sprintboot.dto.GourmetQueryDto;
import com.example.sprintboot.dto.PageDto;
import com.example.sprintboot.entity.Gourmet;
import com.example.sprintboot.service.GourmetService;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@RestController
@RequestMapping("/gourmet")
@Tag(name = "美食管理", description = "美食相关的API接口")
public class GourmetController {

    @Resource
    private GourmetService gourmetService;
    @Autowired
    private InternalResourceViewResolver defaultViewResolver;

    @Operation(summary = "查询所有美食", description = "获取所有美食数据")
    @GetMapping("/selectAll")
    public Result selectAll(){
        List<Gourmet> list=gourmetService.selectAll();
        return Result.success(list);
    }

    @Operation(summary = "根据ID查询美食", description = "根据美食ID查询美食详情")
    @PostMapping("/selectById")
    public Result selectById(@RequestBody GourmetQueryDto queryDto){
        Gourmet gourmet = gourmetService.selectById(queryDto.getId());
        return Result.success(gourmet);
    }

    @Operation(summary = "添加美食", description = "新增一个美食")
    @PostMapping("/add")
    public Result add(@RequestBody Gourmet gourmet){
//        gourmet.setImage(UUID.randomUUID().toString().toUpperCase(Locale.ROOT));
        gourmet.setCreateTime(LocalDateTime.now());
        gourmet.setIsAudit(0);
        gourmet.setViewCount(0);
        gourmet.setLikeCount(0);
        gourmet.setRating(0.0);
        gourmet.setUpvotCount(0);
        gourmetService.add(gourmet);
        return Result.success();
    }

    @Operation(summary = "更新美食", description = "更新美食信息")
    @PutMapping("/update")
    public Result update(@RequestBody Gourmet gourmet){
        gourmet.setUpdateTime(LocalDateTime.now());
        gourmetService.update(gourmet);
        return Result.success();
    }
    @Operation(summary = "删除美食", description = "根据ID删除美食")
    @DeleteMapping("/delete/{id}")
    public Result delete(@Parameter(description = "美食ID", required = true) @PathVariable Integer id){
        gourmetService.delete(id);
        return  Result.success();
    }

    @Operation(summary = "分页查询美食", description = "分页获取美食列表")
    @PostMapping("/page")
    public Result page(@RequestBody PageDto pageDto){
        PageInfo<Gourmet> pageInfo = gourmetService.page(pageDto.getPageNum(), pageDto.getPageSize());
        return Result.success(pageInfo);
    }

    @Operation(summary = "条件查询美食", description = "根据名称等条件分页查询美食")
    @PostMapping("/query")
    public Result query(@RequestBody GourmetQueryDto queryDto) {
        PageInfo<Gourmet> pageInfo = gourmetService.query(queryDto.getTitle(), queryDto.getPageNum(), queryDto.getPageSize());
        return Result.success(pageInfo);
    }

    @Operation(summary = "通过审核状态", description = "")
    @PutMapping("/audit/{id}")
    public Result audit(@PathVariable Integer id){
        Gourmet gourmet = gourmetService.selectById(id);
        gourmet.setIsAudit(1);
        gourmetService.update(gourmet);
        return Result.success();
    }

    @Operation(summary = "上传美食图片", description = "上传美食图片文件并返回图片访问URL")
    @PostMapping("/upload/image")
    public Result uploadImage(@RequestParam("file") MultipartFile file) {
        // 1. 检查文件是否为空
        if (file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        
        // 2. 检查文件类型（可选，增加安全性）
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            return Result.error("文件名不能为空");
        }
        
        String extension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        // 只允许图片格式
        if (!extension.matches("\\.(jpg|jpeg|png|gif|bmp|webp)")) {
            return Result.error("只支持图片格式：jpg, jpeg, png, gif, bmp, webp");
        }
        
        try {
            // 3. 生成新的文件名（使用UUID避免文件名冲突）
            String newFilename = UUID.randomUUID().toString() + extension;
            
            // 4. 设置文件保存路径（在项目根目录下的uploads文件夹）
            String uploadDir = System.getProperty("user.dir") + "/uploads/";
            File dir = new File(uploadDir);
            // 如果目录不存在，创建目录
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 5. 保存文件到服务器
            File destFile = new File(uploadDir + newFilename);
            file.transferTo(destFile);
            
            // 6. 生成访问URL（相对路径）
            String imageUrl = "/uploads/" + newFilename;
            
            // 7. 返回图片URL给前端
            return Result.success(imageUrl);
            
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error("文件上传失败: " + e.getMessage());
        }
    }

    @Operation(summary = "下载美食图片", description = "根据文件名下载图片文件")
    @GetMapping("/download/image/{filename}")
    public ResponseEntity<InputStreamResource> downloadImage(
            @Parameter(description = "文件名", required = true) @PathVariable String filename) {
        try {
            // 1. 构建文件路径
            String uploadDir = System.getProperty("user.dir") + "/uploads/";
            File file = new File(uploadDir + filename);
            
            // 2. 检查文件是否存在
            if (!file.exists() || !file.isFile()) {
                return ResponseEntity.notFound().build();
            }
            
            // 3. 检查文件路径安全性（防止路径遍历攻击）
            String canonicalPath = file.getCanonicalPath();
            String canonicalUploadDir = new File(uploadDir).getCanonicalPath();
            if (!canonicalPath.startsWith(canonicalUploadDir)) {
                return ResponseEntity.badRequest().build();
            }
            
            // 4. 准备文件流
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStreamResource resource = new InputStreamResource(fileInputStream);
            
            // 5. 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + 
                    URLEncoder.encode(filename, StandardCharsets.UTF_8.toString()));
            
            // 6. 根据文件扩展名设置Content-Type
            String contentType = getContentType(filename);
            headers.setContentType(MediaType.parseMediaType(contentType));
            headers.setContentLength(file.length());
            
            // 7. 返回文件流
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
                    
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().build();
        }
    }

    @Operation(summary = "预览美食图片", description = "根据文件名在线预览图片（不强制下载）")
    @GetMapping("/preview/image/{filename}")
    public ResponseEntity<InputStreamResource> previewImage(
            @Parameter(description = "文件名", required = true) @PathVariable String filename) {
        try {
            // 1. 构建文件路径
            String uploadDir = System.getProperty("user.dir") + "/uploads/";
            File file = new File(uploadDir + filename);
            
            // 2. 检查文件是否存在
            if (!file.exists() || !file.isFile()) {
                return ResponseEntity.notFound().build();
            }
            
            // 3. 检查文件路径安全性（防止路径遍历攻击）
            String canonicalPath = file.getCanonicalPath();
            String canonicalUploadDir = new File(uploadDir).getCanonicalPath();
            if (!canonicalPath.startsWith(canonicalUploadDir)) {
                return ResponseEntity.badRequest().build();
            }
            
            // 4. 准备文件流
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStreamResource resource = new InputStreamResource(fileInputStream);
            
            // 5. 设置响应头（预览模式，不强制下载）
            HttpHeaders headers = new HttpHeaders();
            String contentType = getContentType(filename);
            headers.setContentType(MediaType.parseMediaType(contentType));
            headers.setContentLength(file.length());
            
            // 6. 返回文件流（浏览器会直接显示图片）
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
                    
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().build();
        }
    }

    @Operation(summary = "导出Excel", description = "导出美食数据到Excel文件")
    @GetMapping("/export/excel")
    public ResponseEntity<InputStreamResource> exportExcel() {
        try {
            // 1. 获取所有美食数据
            List<Gourmet> gourmetList = gourmetService.selectAll();
            
            // 2. 创建Excel工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("美食列表");
            
            // 3. 创建表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setFontHeightInPoints((short) 12);
            headerStyle.setFont(headerFont);
            headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            
            // 4. 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {"ID", "用户ID", "分类ID", "标题", "内容", "图片", "审核状态", "是否公开", "创建时间", "更新时间"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
            }
            
            // 5. 填充数据
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            int rowNum = 1;
            for (Gourmet gourmet : gourmetList) {
                Row row = sheet.createRow(rowNum++);
                
                row.createCell(0).setCellValue(gourmet.getId() != null ? gourmet.getId() : 0);
                row.createCell(1).setCellValue(gourmet.getUserId() != null ? gourmet.getUserId() : 0);
                row.createCell(2).setCellValue(gourmet.getCategoryId() != null ? gourmet.getCategoryId() : 0);
                row.createCell(3).setCellValue(gourmet.getTitle() != null ? gourmet.getTitle() : "");
                row.createCell(4).setCellValue(gourmet.getContent() != null ? gourmet.getContent() : "");
                row.createCell(5).setCellValue(gourmet.getImage() != null ? gourmet.getImage() : "");
                row.createCell(6).setCellValue(gourmet.getIsAudit() != null ? (gourmet.getIsAudit() == 1 ? "已审核" : "未审核") : "未审核");
                row.createCell(7).setCellValue(gourmet.getIsPublic() != null ? (gourmet.getIsPublic() == 1 ? "公开" : "不公开") : "不公开");
                row.createCell(8).setCellValue(gourmet.getCreateTime() != null ? gourmet.getCreateTime().format(formatter) : "");
                row.createCell(9).setCellValue(gourmet.getUpdateTime() != null ? gourmet.getUpdateTime().format(formatter) : "");
            }
            
            // 6. 自动调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
                // 设置最小列宽
                if (sheet.getColumnWidth(i) < 3000) {
                    sheet.setColumnWidth(i, 3000);
                }
            }
            
            // 7. 将工作簿写入到字节数组输出流
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            workbook.close();
            
            // 8. 创建输入流资源
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            InputStreamResource resource = new InputStreamResource(inputStream);
            
            // 9. 设置响应头
            HttpHeaders responseHeaders = new HttpHeaders();
            String filename = "美食列表_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".xlsx";
            responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + 
                    URLEncoder.encode(filename, StandardCharsets.UTF_8.toString()));
            responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            responseHeaders.setContentLength(outputStream.size());
            
            return ResponseEntity.ok()
                    .headers(responseHeaders)
                    .body(resource);
                    
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().build();
        }
    }

    @Operation(summary = "导入Excel", description = "从Excel文件导入美食数据")
    @PostMapping("/import/excel")
    public Result importExcel(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        
        // 检查文件类型
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || 
            (!originalFilename.endsWith(".xlsx") && !originalFilename.endsWith(".xls"))) {
            return Result.error("只支持Excel文件格式（.xlsx或.xls）");
        }
        
        try {
            // 1. 读取Excel文件
            InputStream inputStream = file.getInputStream();
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            
            // 2. 跳过表头，从第二行开始读取
            List<Gourmet> gourmetList = new ArrayList<>();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);
                if (row == null) {
                    continue;
                }
                
                Gourmet gourmet = new Gourmet();
                
                // 读取每一列的数据
                if (getCellValue(row.getCell(0)) != null && !getCellValue(row.getCell(0)).toString().trim().isEmpty()) {
                    gourmet.setId(Integer.parseInt(getCellValue(row.getCell(0)).toString()));
                }
                if (getCellValue(row.getCell(1)) != null && !getCellValue(row.getCell(1)).toString().trim().isEmpty()) {
                    gourmet.setUserId(Integer.parseInt(getCellValue(row.getCell(1)).toString()));
                }
                if (getCellValue(row.getCell(2)) != null && !getCellValue(row.getCell(2)).toString().trim().isEmpty()) {
                    gourmet.setCategoryId(Integer.parseInt(getCellValue(row.getCell(2)).toString()));
                }
                gourmet.setTitle(getCellValue(row.getCell(3)) != null ? getCellValue(row.getCell(3)).toString() : "");
                gourmet.setContent(getCellValue(row.getCell(4)) != null ? getCellValue(row.getCell(4)).toString() : "");
                gourmet.setImage(getCellValue(row.getCell(5)) != null ? getCellValue(row.getCell(5)).toString() : "");
                
                // 审核状态：已审核=1, 未审核=0
                String auditStatus = getCellValue(row.getCell(6)) != null ? getCellValue(row.getCell(6)).toString() : "";
                gourmet.setIsAudit("已审核".equals(auditStatus) ? 1 : 0);
                
                // 是否公开：公开=1, 不公开=0
                String publicStatus = getCellValue(row.getCell(7)) != null ? getCellValue(row.getCell(7)).toString() : "";
                gourmet.setIsPublic("公开".equals(publicStatus) ? 1 : 0);
                
                // 创建时间和更新时间
                String createTimeStr = getCellValue(row.getCell(8)) != null ? getCellValue(row.getCell(8)).toString() : "";
                if (!createTimeStr.trim().isEmpty()) {
                    try {
                        gourmet.setCreateTime(LocalDateTime.parse(createTimeStr, formatter));
                    } catch (Exception e) {
                        gourmet.setCreateTime(LocalDateTime.now());
                    }
                } else {
                    gourmet.setCreateTime(LocalDateTime.now());
                }
                
                String updateTimeStr = getCellValue(row.getCell(9)) != null ? getCellValue(row.getCell(9)).toString() : "";
                if (!updateTimeStr.trim().isEmpty()) {
                    try {
                        gourmet.setUpdateTime(LocalDateTime.parse(updateTimeStr, formatter));
                    } catch (Exception e) {
                        // 如果解析失败，不设置更新时间
                    }
                }
                
                gourmetList.add(gourmet);
            }
            
            workbook.close();
            inputStream.close();
            
            // 3. 批量保存数据
            int successCount = 0;
            int failCount = 0;
            int updateCount = 0;
            int insertCount = 0;
            
            for (Gourmet gourmet : gourmetList) {
                try {
                    if (gourmet.getId() != null && gourmet.getId() > 0) {
                        // 如果Excel中有ID，先检查数据库中是否存在
                        Gourmet existingGourmet = gourmetService.selectById(gourmet.getId());
                        if (existingGourmet != null) {
                            // 记录存在，执行更新
                            gourmet.setUpdateTime(LocalDateTime.now());
                            gourmetService.update(gourmet);
                            updateCount++;
                        } else {
                            // 记录不存在，但Excel中有ID，可以选择：
                            // 方案1：使用Excel中的ID插入（需要确保ID不会被数据库自增冲突）
                            // 方案2：忽略ID，让数据库自增生成新ID
                            // 这里采用方案2：忽略ID，执行新增
                            Integer oldId = gourmet.getId();
                            gourmet.setId(null); // 清空ID，让数据库自增
                            gourmet.setCreateTime(LocalDateTime.now());
                            if (gourmet.getIsAudit() == null) {
                                gourmet.setIsAudit(0);
                            }
                            gourmetService.add(gourmet);
                            insertCount++;
                            System.out.println("Excel中ID为 " + oldId + " 的记录不存在，已作为新记录插入");
                        }
                    } else {
                        // Excel中没有ID，执行新增
                        gourmet.setCreateTime(LocalDateTime.now());
                        if (gourmet.getIsAudit() == null) {
                            gourmet.setIsAudit(0);
                        }
                        gourmetService.add(gourmet);
                        insertCount++;
                    }
                    successCount++;
                } catch (Exception e) {
                    e.printStackTrace();
                    failCount++;
                    System.err.println("导入失败，数据：" + gourmet.toString() + "，错误：" + e.getMessage());
                }
            }
            
            String resultMsg = String.format("导入完成！总计：%d条，成功：%d条（更新：%d条，新增：%d条），失败：%d条", 
                    gourmetList.size(), successCount, updateCount, insertCount, failCount);
            return Result.success(resultMsg);
            
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error("文件读取失败: " + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("导入失败: " + e.getMessage());
        }
    }

    /**
     * 获取单元格的值
     */
    private Object getCellValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue();
                } else {
                    // 如果是整数，返回整数；否则返回double
                    double numericValue = cell.getNumericCellValue();
                    if (numericValue == (int) numericValue) {
                        return (int) numericValue;
                    } else {
                        return numericValue;
                    }
                }
            case BOOLEAN:
                return cell.getBooleanCellValue();
            case FORMULA:
                return cell.getCellFormula();
            default:
                return null;
        }
    }

    /**
     * 根据文件名获取Content-Type
     */
    private String getContentType(String filename) {
        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
        switch (extension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "bmp":
                return "image/bmp";
            case "webp":
                return "image/webp";
            default:
                return "application/octet-stream";
        }
    }
}
